package ca.kooki.codesnippet;

import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;

import junit.framework.Assert;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import ca.kooki.codesnippet.core.SearchInput;
import ca.kooki.codesnippet.core.SystemDate;
import ca.kooki.codesnippet.core.User;

public class TagTest 
{

  CodeSnippet mysnippet;
  
  @Before
  public void setUp()
  {
    mysnippet = new CodeSnippet("myt","myk1 myk2 myk3","void(0)");
  }
  
  @After
  public void tearDown()
  {
    SystemDate.reset();
  }
  
  @Test
  public void Constructor()
  {
    
    Tag tag = new Tag("t","k1 k2 k3",mysnippet,"aforward");
    
    Assert.assertEquals("t",tag.getTitle());
    Assert.assertEquals("k1 k2 k3",tag.getKeywords());
    Assert.assertEquals("aforward",tag.getUser().getName());
    Assert.assertEquals(mysnippet, tag.getCodeSnippet());
    
    String[] allKeywords = tag.getKeywordList();
    Assert.assertEquals(3, allKeywords.length);
    Assert.assertEquals("k1", allKeywords[0]);
    Assert.assertEquals("k2", allKeywords[1]);
    Assert.assertEquals("k3", allKeywords[2]);
    
  }

  @Test
  public void ConstructorWithUser()
  {
    
    User user = new User("aforward");
    user.setId("10");
    Tag tag = new Tag("t","k1 k2 k3",mysnippet,user);
    
    Assert.assertEquals("t",tag.getTitle());
    Assert.assertEquals("k1 k2 k3",tag.getKeywords());
    Assert.assertEquals(user,tag.getUser());
    Assert.assertEquals(mysnippet, tag.getCodeSnippet());
    
    String[] allKeywords = tag.getKeywordList();
    Assert.assertEquals(3, allKeywords.length);
    Assert.assertEquals("k1", allKeywords[0]);
    Assert.assertEquals("k2", allKeywords[1]);
    Assert.assertEquals("k3", allKeywords[2]);
    
  }

  
  @Test
  public void IgnoreKeywordWhiteSpace()
  {
    Tag tag = new Tag("t"," k1   k2 k3  ",mysnippet,"void(0);");

    String[] allKeywords = tag.getKeywordList();
    Assert.assertEquals(3, allKeywords.length);
    Assert.assertEquals("k1", allKeywords[0]);
    Assert.assertEquals("k2", allKeywords[1]);
    Assert.assertEquals("k3", allKeywords[2]);

  }
  
  @Test
  public void ToStringShowsAll()
  {
    Tag tag = new Tag("t","k",mysnippet,"c");
    Assert.assertEquals("t;k;[myt;myk1 myk2 myk3;void(0)];c", tag.toString());
    
  }
  
  @Test
  public void NotEqualsNull()
  {
    Tag tag = new Tag("t","k",mysnippet,"c");
    Assert.assertFalse(tag.equals(null));
    Assert.assertFalse(tag.equals("blah"));
  }

  @Test
  public void NotEqualsDifferentSnippet()
  {
    Tag tag = new Tag("t","k",mysnippet,"c");
    Tag compareTo = new Tag("t","k",new CodeSnippet("x","y","z"),"c");

    Assert.assertFalse(tag.equals(compareTo));

  }
  
  @Test
  public void NotEqualsWrongData()
  {
    Tag tag = new Tag("t","k",mysnippet,"c");
    Tag compareTo = null;
    
    compareTo = new Tag("t1","k",mysnippet,"c");
    Assert.assertFalse(tag.equals(compareTo));

    compareTo = new Tag("t","k1",mysnippet,"c");
    Assert.assertFalse(tag.equals(compareTo));

    compareTo = new Tag("t","k",mysnippet,"c1");
    Assert.assertFalse(tag.equals(compareTo));

  }

  @Test
  public void NotEqualsWrongId()
  {
    Tag tag = new Tag("t","k",mysnippet,"c");
    Tag compareTo = null;
    
    compareTo = new Tag("t","k",mysnippet,"c");
    
    tag.setId("10");
    compareTo.setId("11");
    Assert.assertFalse(tag.equals(compareTo));
  }

  @Test
  public void EqualsSameIdIgnoresOtherData()
  {
    Tag tag = new Tag("t1","k1",mysnippet,"c1");
    Tag compareTo = new Tag("t2","k2",mysnippet,"c2");
    
    tag.setId("10");
    compareTo.setId("10");
    
    Assert.assertTrue(tag.equals(compareTo));
  }

  
  @Test
  public void EqualsAllTheSame()
  {
    Tag tag = new Tag("t","k",mysnippet,"c");
    Tag compareTo = new Tag("t","k",mysnippet,"c");
    Assert.assertTrue(tag.equals(compareTo));
  }

  @Test
  public void EqualsOneWithoutAnId()
  {
    Tag tag = new Tag("t","k",mysnippet,"c");
    Tag compareTo = new Tag("t","k",mysnippet,"c");
    
    tag.setId("10");
    
    Assert.assertTrue(tag.equals(compareTo));
    Assert.assertTrue(compareTo.equals(tag));
  }

  
  @Test
  public void IsOfficial()
  {
    Tag tag = new Tag("t","k",mysnippet,"c");
    Assert.assertEquals(false, tag.isOfficial());
    tag.setId("10");
    Assert.assertEquals(true, tag.isOfficial());
  }
  
  @Test(expected=UnsupportedOperationException.class)
  public void getIdNotSetYet()
  {
    Tag tag = new Tag("t","k",mysnippet,"c");
    tag.getId();
  }

  @Test
  public void cannotSetIdToSameNumberMultipleTimes()
  {
    Tag tag = new Tag("t","k",mysnippet,"c");
    tag.setId("10");
    tag.setId("10");
    Assert.assertEquals("10", tag.getId());
  }

  
  @Test(expected=UnsupportedOperationException.class)
  public void cannotSetIdToDifferentNumber()
  {
    Tag tag = new Tag("t","k",mysnippet,"c");
    tag.setId("10");
    tag.setId("11");
  }

  
  @Test
  public void getIdOkay()
  {
    Tag tag = new Tag("t","k",mysnippet,"c");
    tag.setId("10");
    Assert.assertEquals("10", tag.getId());
  }
  
  @Test
  public void Updated() throws ParseException
  {
    DateFormat format = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT);
    Date newNow = format.parse("Nov 4, 2003 8:14 PM");
    SystemDate.setNowTo(newNow);
    
    Tag tag = new Tag("t","k",mysnippet,"c");
    Assert.assertEquals(newNow, tag.getUpdated());
    
    Date lastUpdated = format.parse("Nov 2, 2003 8:14 PM");
    tag.setUpdated(lastUpdated);
    Assert.assertEquals(lastUpdated, tag.getUpdated());
    
  }
  
  @Test
  public void IsRelevantEmptyIsTrue()
  {
    Tag tag = new Tag("t","k",mysnippet,"aforward");
    Assert.assertEquals(true, tag.isRelevant(""));
    Assert.assertEquals(true, tag.isRelevant("/"));
    Assert.assertEquals(true, tag.isRelevant((String)null));
    
  }
  
  @Test
  public void isRelevantNoUserName()
  {
    Tag tag = new Tag("t","k k2",mysnippet,"aforward");
    Assert.assertEquals(true, tag.isRelevant("k"));
    Assert.assertEquals(true, tag.isRelevant("k2"));
    Assert.assertEquals(false, tag.isRelevant("k3"));
  }
  
  @Test
  public void IsRelevantUserName()
  {
    Tag tag = new Tag("t","k",mysnippet,"aforward");
    Assert.assertEquals(true, tag.isRelevant("/aforward"));
    Assert.assertEquals(false, tag.isRelevant("/notaforwrd"));
  }

  @Test
  public void IsRelevantUserNameAndKeywords()
  {
    Tag tag = new Tag("t","k1 k2",mysnippet,"aforward");
    Assert.assertEquals(true, tag.isRelevant("/aforward/k1"));
    Assert.assertEquals(true, tag.isRelevant("/aforward/k2"));
    Assert.assertEquals(true, tag.isRelevant("/aforward/k1/k2"));
    Assert.assertEquals(false, tag.isRelevant("/aforward/k3"));
  }

  @Test
  public void IsRelevantFromSearchInput()
  {
    Tag tag = new Tag("t","k",mysnippet,"aforward");
    Assert.assertEquals(true, tag.isRelevant(new SearchInput("/aforward")));
    Assert.assertEquals(false, tag.isRelevant(new SearchInput("/notaforward")));
  }

}
